package com.aldobucchi.mouse
{
	
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import com.aldobucchi.core.dependency.DependencySpec;
	import com.aldobucchi.utils.App;
	
	
	
	public class MouseHoverTracker extends MouseTrackerBase
	{
		
		
		//////////////
		// strategies
		/////////////////////////
		
		public static const STRATEGY_HIT_TEST					:int = 1;
		public static const STRATEGY_HIT_TEST_SHAPE_FLAG		:int = 2;
		public static const STRATEGY_RECT						:int = 3;
		public static const STRATEGY_BOUNDS					:int = 4;
		
		
		/**
		 * Use width and height properties in conjunction with 
		 * matrix transformations.
		 * This will work even if the target is invisible
		 * or has no background color.
		 * 
		*/		
		public static const STRATEGY_WH						:int = 5;
		
		
		
		//////////////
		// events
		/////////////////////////
		
		public static const hoverChanged		:String = "hoverChanged";
		public static const strategyChanged	:String = "strategyChanged";
		
		
		
		
		
		///////////////////////////////////////
		// hover
		///////////////////////////////////////
		
		private var _hover:Boolean;
		[Bindable( hoverChanged )]
		public function get hover( ):Boolean
		{
			return _hover;
		}

		
		///////////////////////////////////////
		// strategy
		///////////////////////////////////////
		
		private var strategySpec:DependencySpec = new DependencySpec( 
			"strategy", 
			strategyChanged, 
			null, 
			false, 
			STRATEGY_HIT_TEST 
			);
			
		[Bindable( strategyChanged )]
		public function get strategy( ):int
		{
			return dh.getDependencyValue( strategySpec );
		}
		public function set strategy( v:int ):void
		{
			dh.setDependencyValue( strategySpec, v );
		}
		
		
		

		///////////////////////////////////////
		// constructor
		///////////////////////////////////////
		
		public function MouseHoverTracker( )
		{
			App.app.addEventListener( Event.ENTER_FRAME, onEnterFrame, false, 0, true );
		}
		
		
		
		
		protected function onEnterFrame( event:Event ):void
		{
			update( );
		}
		
		
		
		
		override protected function dependenciesUpdated( ):void
		{
			update( );
		}
		
		
		
		
		private function update( ):void
		{
			
			if ( ! enabled )
			{
				setNewHover( false );
				return;			
			}	
			
			
			try
			{
				
				var p:Point = MouseUtil.getMousePointOnStage( );

				var result:Boolean;
				var rect:Rectangle;
				
				switch ( strategy )
				{
				
					case STRATEGY_HIT_TEST :
						result = target.hitTestPoint( p.x, p.y );
					break;

					case STRATEGY_HIT_TEST_SHAPE_FLAG : 
						result = target.hitTestPoint( p.x, p.y, true );
					break;

					case STRATEGY_RECT :
						result = target.getRect( target.stage ).containsPoint( p );
					break;
					
					case STRATEGY_BOUNDS : 
						result = target.getBounds( target.stage ).containsPoint( p );
					break;

					case STRATEGY_WH : 
						result = new Rectangle(	0, 0, target.width, target.height )
											.containsPoint( target.globalToLocal( p ) );
					break;
				
				}				
				
				
				setNewHover( result );			
			
			
			}
			catch ( e:Error )
			{
				setNewHover( false );
			}		
		
		}
		
		
		
		
		
		
		
		
		
		
		private function setNewHover( v:Boolean ):void
		{
			if ( v == _hover )
				return;
		
			_hover = v;
		
			dispatchEvent( new Event( hoverChanged ) );
		}
		
	}

}